#include "DTF.h"

DTF_T* DTF_t;



//************************************
// Method:    	CALCU_SAMA						//< SAMA运算函数
// Programmer:  duan
// Time:		2019/03/19
// Returns:   	bool							//< 成功：true；失败：false
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	float dt						//< 运算周期
// Parameter: 	bool * DI						//< 数字量输入值数组指针
// Parameter: 	bool * DO						//< 数字量输出值数组指针
// Parameter: 	bool * AI						//< 模拟量输入值数组指针
// Parameter: 	bool * AO						//< 模拟量输出值数组指针
//************************************
bool CALCU_SAMA(DTF)(Model_Base_t* arg, float dt, bool* DI, bool* DO, float* AI, float* AO)
{
#define TIME_CLEARZERO (\
{\
	if(RunTime_Sum[0] >= 1E8 || T_Sum[0] >= 1E8)\
	{\
		RunTime_Sum[0] = 0;\
		T_Sum[0] = 0;\
	}\
})
	/****************变量定义区开始**************/
	int i;
	float u;
	float y;

	/*<<<<<定义输入变量>>>>>*/
	float defAI;			
	
	/*<<<<<定义输出变量>>>>>*/
	float Output_Value;			
	
	/*<<<<<定义参数变量>>>>>*/
	float Init_Value;			//< 初始值
	float K;					//< 比例系数
	float T;					//< 采样时间
	int n;						//< 分母阶数
	int m;						//< 分子阶数
	float b[20];				//< 分子序列	  b0、b1、b2.......bm
	float a[20];				//< 分母序列   a0、a1、a2.......an    限制n最大为19
	
	
	//< float B0;               //< 该参数由上位下发得到，但应不属于可调参数
	//< int N;                  //< 该参数由上位下发得到，但应不属于可调参数
	//< int M;                  //< 该参数由上位下发得到，但应不属于可调参数

	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<定义中间变量>>>>>*/
	float* T_Sum;
	float* RunTime_Sum;
	float* last_y[20];
	float* last_u[20];

	/****************变量定义区结束**************/

	NAME(DTF)* Obj = (NAME(DTF)*)arg;

	/****************变量赋值**************/
	/*<<<<<输入变量赋值>>>>>*/
	defAI = AI[0];
	
	/*<<<<<参数变量赋值>>>>>*/
	 Init_Value = Obj->Par.Init_Value;      
	 K = Obj->Par.K;               
	 T = Obj->Par.T; 
	 n = Obj->Par.n;
	 m = Obj->Par.m;
	 for (i = 0; i < 20; i++)
	 {
		 a[i] = Obj->Par.a[i];
		 b[i] = Obj->Par.b[i];
	 }
          
	/*<<<<<中间变量赋值>>>>>*/
	 T_Sum = &(Obj->Sta.dTime);
	 RunTime_Sum = &(Obj->Sta.RunTime_Sum);
	 for (i = 0; i < 20; i++)
	 {
		 last_y[i] = &(Obj->Sta.last_y[i]);
		 last_u[i] = &(Obj->Sta.last_u[i]);
	 }
	
	/**************变量赋值结束************/

	/********************************************/
	/**************算法功能实现开始**************/
	/********************************************/
	 //if (T < 2 * dt)             //< 联系上位，采样时间必须大于2*dt
	 //{
		// Output_Value = Init_Value;		
		// return true;					

	 //}

	 if (dt * RunTime_Sum[0] < T_Sum[0])						//< duan 没有达到采样时间
	 {
		 RunTime_Sum[0] = (float)(RunTime_Sum[0] + 1.0);
		
		 /* if (RunTime_Sum[0] >= 1E8)							//< duan 20191122注释
		  {
			  RunTime_Sum[0] = 0;
			  T_Sum[0] = 0;
		  }*/
		 TIME_CLEARZERO;

		 Output_Value = last_y[0][0] + Init_Value;
		 AO[0] = Output_Value;
		 return true;
	 }


	 RunTime_Sum[0] = (float)(RunTime_Sum[0] + 1.0);			//< DTF函数每dt运算一次，Times加1	
	
	  /*if (RunTime_Sum[0] >= 1E8)								//< duan 20191122注释
	  {
		  RunTime_Sum[0] = 0;
		  T_Sum[0] = 0;
	  }*/
	 TIME_CLEARZERO;

	 /*T_Sum[0] += T * dt;*/									//< duan 20191117 注释
	 T_Sum[0] += T;												//< 20191117 采样时间为秒数

	 //< 计算u(k),将其存入last_u第0个单元
	 u = defAI;
	 last_u[0][0] = u;

	 //< 计算y(k)
	 y = 0;  //< 累加器清零
	 for (i = 1; i < n + 1; i++)								//< 20191117 需要n个单元
		 y = y - 1 / a[0] * (a[i] * last_y[i-1][0]);
	 for (i = 0; i < m + 1; i++)								//< 20191117 需要m+1个单元
		 y = y + K / a[0] * (b[i] * last_u[i][0]);
	 
	 //< 把y各采样时刻值向右平移一个单元
	 for (i = n - 1; i > 0; i--)								//< 20191117 修改
		 last_y[i][0] = last_y[i - 1][0];
	 
	 last_y[0][0] = y;											//< 把y(K)存入第0个单元

	  //< 把u各采样时刻值向右平移一个单元
	 for (i = m; i > 0; i--)
		 last_u[i][0] = last_u[i - 1][0];
	 

	 Output_Value = y + Init_Value;							

	 /*if (T_Sum[0] >= 1E8)										//< duan 20191122注释
	 {
		 RunTime_Sum[0] = 0;
		 T_Sum[0] = 0;
	 }*/
	 TIME_CLEARZERO;
	/********************************************/
	/**************算法功能实现结束**************/
	/********************************************/	

	/****************运算结果输出**************/
	AO[0] = Output_Value;
	/**************运算结果输出完毕************/
	return true;

#undef TIME_CLEARZERO 
}



//************************************
// Method:    	BCPARA							//< 广播SAMA参数变量函数（无参数需要广播的模块直接将BCPara函数设置为NULL即可）
// Programmer:  duan
// Time:		2019/03/19
// Returns:   	int								//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 广播SAMA参数的数据包的指针
//************************************
int BC_PARA(DTF)(Model_Base_t* arg, void** Data)
{
	NAME(DTF)* Obj = (NAME(DTF)*)arg;
	BC_PARA_PUBLIC(Obj);
	return 0;
}



//************************************
// Method:    	BAK_STA							//< 备份SAMA运算中间参数
// Programmer:  duan
// Time:		2019/03/19
// Returns:   	int								//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 指定模块类型链表的指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int BAK_STA(DTF)(Model_Base_t* arg, void** Data)
{
	NAME(DTF)* Obj = (NAME(DTF)*)arg;
	BAK_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	ANA_STA							//< 解析备份的SAMA运算中间参数
// Programmer:  duan
// Time:		2019/03/19
// Returns:   	int								//< 成功：返回解析字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int ANA_STA(DTF)(Model_Base_t* arg, void** Data)
{
	NAME(DTF)* Obj = (NAME(DTF)*)arg;
	ANA_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	CHANGE_PAR				//< 在线修改模块参数函数
// Programmer:  duan
// Time:		2019/03/19
// Returns:   	int						//< 读取字节长度计数值
// Parameter: 	Model_Base_t* arg		//< 指定模块类型链表的指针
// Parameter: 	void** Data				//< 存放数据包当前指针位置的地址
//************************************
int CHANGE_PAR(DTF)(Model_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(DTF)*)arg)->Par, Data[0]);
	return _iLen;
}



//************************************
// Method:    	INIT_STAPAR						//< 初始化模块运算中间参数
// Programmer:  duan
// Time:		2019/03/19
// Parameter: 	Model_Base_t* arg				//< 模块参数结构体指针
//************************************
void INIT_STAPAR(DTF)(Model_Base_t* arg)
{
	NAME(DTF)* name = (NAME(DTF)*)arg;
	/****************初始化中间变量结构体**************/
	memset(&(name->Sta), 0, sizeof(name->Sta));
	/**************初始化中间变量结构体结束************/

	/****************对中间变量结构体的相关参数进行赋值**************/

	/**************对中间变量结构体的相关参数进行赋值结束************/
}
